home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
wics.zip
/
PRINTER.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-05
|
22KB
|
716 lines
/*==========================================================================================*/
/* */
/* Windows Interface Construction Set */
/* Version 1.00 */
/* */
/*------------------------------------------------------------------------------------------*/
/* PRINTER.CPP - Windows Printing Classes */
/*------------------------------------------------------------------------------------------*/
/* */
/* Copyright ⌐ 1993 by Microdyne Development Technologies */
/* All rights reserved. */
/* */
/*==========================================================================================*/
#include <printer.h>
#include <safepool.h>
#include <wics.h>
/*------------------------------------------------------------------------------------------*/
/* Helper functions for the YieldProc procedure. */
/*------------------------------------------------------------------------------------------*/
BOOL ProcessDlgMsg(LPMSG PMessage, PTApplication Application)
{
if (Application->KBHandlerWnd && Application->KBHandlerWnd->HWindow)
return IsDialogMessage(Application->KBHandlerWnd->HWindow, PMessage);
else
return FALSE;
}
BOOL ProcessAccels(LPMSG PMessage, PTApplication Application)
{
return Application->HAccTable &&
TranslateAccelerator(Application->MainWindow->HWindow, Application->HAccTable, PMessage);
}
BOOL ProcessMDIAccels(LPMSG PMessage, PTApplication Application)
{
return (PTWindowsObject)(Application->MainWindow->GetClient()) &&
TranslateMDISysAccel(((PTWindowsObject)(Application->MainWindow->GetClient()))->HWindow, PMessage);
}
BOOL ProcessAppMsg(LPMSG PMessage)
{
PTApplication Application = GetApplicationObject();
if ( Application->KBHandlerWnd )
if ( Application->KBHandlerWnd->IsFlagSet(WB_MDICHILD) )
return ProcessMDIAccels(PMessage, Application) ||
ProcessDlgMsg(PMessage, Application) ||
ProcessAccels(PMessage, Application);
else
return ProcessDlgMsg(PMessage, Application) ||
ProcessMDIAccels(PMessage, Application) ||
ProcessAccels(PMessage, Application);
else
return ProcessMDIAccels(PMessage, Application) ||
ProcessAccels(PMessage, Application);
}
/*------------------------------------------------------------------------------------------*/
/* YieldProc */
/*------------------------------------------------------------------------------------------*/
/* */
/* Abstract: */
/* */
/* This procedure is used to allow messages waiting in the message queue to be processed */
/* by other windows while the printing process is being done. This allows Windows to */
/* multi-task during the (potentially) long printing process. */
/* */
/*------------------------------------------------------------------------------------------*/
BOOL FAR PASCAL _export YieldProc(BOOL UserAbort)
{
MSG Msg;
while (!UserAbort && PeekMessage(&Msg, NULL, NULL, NULL, PM_REMOVE))
if (!ProcessAppMsg(&Msg))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return (!UserAbort);
}
/*------------------------------------------------------------------------------------------*/
/* Class TPrintedPage */
/*------------------------------------------------------------------------------------------*/
/* */
/* Abstract: */
/* */
/* TPrintedPage represents the physical printed document which is to be sent to a printer */
/* to be printed. TPrintedPage does the rendering of the document onto the printer. For */
/* every document, or document type, a corresponding TPrintedPage class should be created. */
/* */
/*------------------------------------------------------------------------------------------*/
TPrintedPage::TPrintedPage(Pchar ATitle)
{
HDC hdc ;
Title = new char[lstrlen(ATitle)+1];
lstrcpy (Title, ATitle);
hdc = GetDC (NULL);
ScreenDpi.x = GetDeviceCaps (hdc, LOGPIXELSX);
ScreenDpi.y = GetDeviceCaps (hdc, LOGPIXELSY);
ReleaseDC (NULL, hdc);
}
TPrintedPage::~TPrintedPage()
{
delete Title;
}
BOOL TPrintedPage::IsNextPage()
{
return FALSE;
}
/* This member takes a LOGFONT structure filled with a font created for the screen and
* computes the point size of the font. This routine can be used to obtain a point size
* of a screen font so that the font can be rendered on the page at the appropriate size.
*/
int TPrintedPage::GetPointSize (LOGFONT FAR *lplf)
{
int PixelSize;
int PointSize;
int LogPixelsY;
int RoundFactor;
DWORD lIntermediate;
HDC hdc;
/* The font size will come in pixel height. We must convert pixel height
* to its equivalent point size.
*
* First, if the input parameter is positive, eliminate the internal
* leading value to get the font height.
*/
if ( (int) lplf->lfHeight > 0 )
{
HFONT hCurrentFont ;
TEXTMETRIC tm;
hdc = GetDC (NULL);
hCurrentFont = CreateFontIndirect(lplf);
SelectObject( hdc, hCurrentFont );
GetTextMetrics (hdc, &tm);
PixelSize = lplf->lfHeight - tm.tmInternalLeading ;
ReleaseDC (NULL, hdc);
DeleteObject (hCurrentFont);
}
else
PixelSize = abs(lplf->lfHeight);
/* Now that we have the pixel height, calcuate the point size */
hdc = GetDC (NULL);
LogPixelsY = GetDeviceCaps (hdc, LOGPIXELSY);
ReleaseDC (NULL, hdc);
RoundFactor = LogPixelsY / 2 ;
lIntermediate = 72L * PixelSize + RoundFactor ;
PointSize = (int) (lIntermediate / LogPixelsY );
return PointSize;
}
/*------------------------------------------------------------------------------------------*/
/* Class TPrinterAbortDlg */
/*------------------------------------------------------------------------------------------*/
/* */
/* Abstract: */
/* */
/* TPrinterAbortDlg represents the "printing" dialog box that is displayed while TPrinter */
/* is printing a TPrintedPage. */
/* */
/*------------------------------------------------------------------------------------------*/
static BOOL RegFails(void *AWindowsObject, void *)
{
return !((PTWindowsObject)AWindowsObject)->Register();
}
TPrinterAbortDlg::TPrinterAbortDlg(PTWindowsObject AParent, PTDialogTemplate ADialogTemplate, Pchar Title, LPSTR Device, LPSTR Port, BOOL& fUserAbort)
: TIndirectDialog(AParent, ADialogTemplate)
{
LPCONTROLDATA lpcd;
LPSTR lpText;
WORD FAR * lpWord;
pfUserAbort = &fUserAbort;
ATitle = Title;
ADevice = Device;
APort = Port;
MaxPage = 0;
CurrentPage = 0;
}
TPrinterAbortDlg::~TPrinterAbortDlg()
{
}
void TPrinterAbortDlg::SetupWindow()
{
char szDevice[80];
TIndirectDialog::SetupWindow();
EnableMenuItem(GetSystemMenu(HWindow, FALSE), SC_CLOSE, MF_GRAYED);
SendDlgItemMsg (ID_TITLE, WM_SETTEXT, 0, (LPARAM) ATitle);
wsprintf (szDevice, "on the %s Printer", ADevice);
SendDlgItemMsg (ID_DEVICE, WM_SETTEXT, 0, (LPARAM) szDevice);
wsprintf (szDevice, "connected to %s", APort);
SendDlgItemMsg (ID_PORT, WM_SETTEXT, 0, (LPARAM) szDevice);
SendDlgItemMsg (ID_PAGEOFPAGE, WM_SETTEXT, 0, (LPARAM) "");
}
void TPrinterAbortDlg::SetMaxPage (int p)
{
char szLine[80];
MaxPage = p;
if ( MaxPage )
{
if ( MaxPage == -1 )
wsprintf (szLine, "Printing page %i . . .", CurrentPage);
else
wsprintf (szLine, "Printing page %i of %i", CurrentPage, MaxPage);
SendDlgItemMsg (ID_PAGEOFPAGE, WM_SETTEXT, 0, (LPARAM) szLine);
}
}
void TPrinterAbortDlg::SetCurrentPage (int p)
{
char szLine[80];
CurrentPage = p;
if ( MaxPage )
{
if ( MaxPage == -1 )
wsprintf (szLine, "Printing page %i . . .", CurrentPage);
else
wsprintf (szLine, "Printing page %i of %i", CurrentPage, MaxPage);
SendDlgItemMsg (ID_PAGEOFPAGE, WM_SETTEXT, 0, (LPARAM) szLine);
}
}
void TPrinterAbortDlg::WMCommand(RTMessage)
{
*pfUserAbort = TRUE;
}
/*------------------------------------------------------------------------------------------*/
/* Class TPrinter */
/*------------------------------------------------------------------------------------------*/
/* */
/* Abstract: */
/* */
/* TPrinter represents the physical printer device. To print a TPrintedPage, send the */
/* TPrintedPage to the TPrinter's Print function. */
/* */
/*------------------------------------------------------------------------------------------*/
TPrinter::TPrinter()
{
hDevNames = NULL;
hDevMode = NULL;
DeviceModule = 0;
Error = 0;
/* Determine the version of Windows...
*
* The following code sets fBefore31 to TRUE if the version of Windows that is currently
* running is a version prior to Version 3.1. If the current version of Windows is
* Version 3.1 or higher, fBefore31 is set to FALSE.
*
* This flag is used throughout the code to impliment version specific code.
*/
if ( LOBYTE(LOWORD(GetVersion())) < 3 )
fBefore31 = TRUE;
else
if ( LOBYTE(LOWORD(GetVersion())) == 3 )
if ( HIBYTE(LOWORD(GetVersion())) == 0 )
fBefore31 = TRUE;
else
fBefore31 = FALSE;
else
fBefore31 = FALSE;
SetDevice(); // Associate with default printer
}
// Deallocate allocated resources
TPrinter::~TPrinter()
{
ClearDevice();
}
// Clears the association of this object with the current device
void TPrinter::ClearDevice()
{
if ( hDevNames != NULL )
{
GlobalFree (hDevNames);
hDevNames = NULL;
}
if ( hDevMode != NULL )
{
GlobalFree (hDevMode);
hDevMode = NULL ;
}
if ((int)DeviceModule >= 32)
{
FreeLibrary(DeviceModule);
DeviceModule = 0;
}
Status = PSTAT_UNASSOCIATED;
}
/* Associates the printer object with a new device. If the ADevice parameter is NULL the
* Windows default printer is used, otherwise, the parameters must be ones contained in the
* [devices] section of the WIN.INI file.
*/
void TPrinter::SetDevice()
{
PRINTDLG pd ;
if ( hDevNames != NULL )
{
GlobalFree (hDevNames);
hDevNames = NULL;
}
if ( hDevMode != NULL )
{
GlobalFree (hDevMode);
hDevMode = NULL ;
}
pd.lStructSize = sizeof(PRINTDLG);
pd.hDevMode = NULL;
pd.hDevNames = NULL;
pd.Flags = PD_RETURNDEFAULT ;
if ( PrintDlg ( &pd ) )
{
hDevMode = pd.hDevMode ;
hDevNames = pd.hDevNames ;
Status = PSTAT_OK;
}
else
Status = PSTAT_UNASSOCIATED;
}
// Configure brings up a dialog as a child of the given window
// to configure the associated printer driver.
void TPrinter::Configure(PTWindowsObject Window)
{
PRINTDLG pd ;
pd.lStructSize = sizeof(PRINTDLG);
pd.hwndOwner = Window->HWindow;
pd.hDevMode = hDevMode;
pd.hDevNames = hDevNames;
pd.hDC = NULL;
pd.Flags = PD_PRINTSETUP | PD_SHOWHELP;
pd.hInstance = NULL;
if ( PrintDlg (&pd) )
{
hDevMode = pd.hDevMode;
hDevNames = pd.hDevNames;
Status = PSTAT_OK;
}
else
Status = PSTAT_UNASSOCIATED;
}
// Returns a device context for the associated printer, 0 if an
// error occurs or Status is != PSTAT_OK
HDC TPrinter::GetDC(PTWindowsObject ParentWin, Rint nCopies, Rint nFromPage, Rint nToPage)
{
PRINTDLG pd ;
pd.lStructSize = sizeof(PRINTDLG);
pd.hwndOwner = ParentWin->HWindow;
pd.hDevMode = hDevMode;
pd.hDevNames = hDevNames;
pd.hDC = NULL;
pd.nCopies = nCopies;
pd.nFromPage = nFromPage;
pd.nToPage = nToPage;
pd.nMinPage = 1;
pd.nMaxPage = 9999;
pd.Flags = PD_RETURNDC | PD_ALLPAGES | PD_SHOWHELP | PD_USEDEVMODECOPIES ;
pd.hInstance = NULL;
if ( Status == PSTAT_OK )
{
if ( PrintDlg (&pd) )
{
hDevMode = pd.hDevMode;
hDevNames = pd.hDevNames;
nFromPage = pd.nFromPage;
nToPage = pd.nToPage;
nCopies = pd.nCopies;
return pd.hDC ;
}
}
return 0;
}
BOOL TPrinter::Print(PTWindowsObject ParentWin, PTPrintedPage Printout)
{
typedef BOOL (FAR PASCAL *PTYieldProc)( BOOL );
int i;
int nCopies;
int nFromPage, nToPage;
int nMaxPage;
PTYieldProc YieldProcInst;
WORD PageNumber;
LPSTR lpName;
LPSTR Device;
LPSTR Port;
DEVNAMES FAR * lpDevNames;
PTDialogTemplate ADialogTemplate;
BOOL result = FALSE; // Assume error occurred
fUserAbort = FALSE; // Assume the user does not wish to cancel the print
Error = 0; // Clear Error Flag
/* Make sure all the required objects exist and that they are properly initialized...
*/
if ( Printout == NULL )
return result;
if ( ParentWin == NULL )
return result;
if ( Status != PSTAT_OK )
{
Error = SP_ERROR;
ReportError(ParentWin, Printout);
return result;
}
/* Get a handle to the Device Context for the printer...
*/
nMaxPage = Printout->GetMaxPage();
nCopies = 1;
nFromPage = 1 ;
nToPage = ( nMaxPage < 1 ) ? 9999 : nMaxPage ;
PrnDC = GetDC(ParentWin, nCopies, nFromPage, nToPage);
if ( PrnDC == 0 )
return result;
/* Display the "Printing" dialog box...
*/
lpDevNames = (DEVNAMES FAR *) GlobalLock(hDevNames);
lpName = (Pchar) lpDevNames ;
Device = (lpName + lpDevNames->wDeviceOffset);
Port = (lpName + lpDevNames->wOutputOffset);
ADialogTemplate = new TDialogTemplate ( DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU,
84, 46, 142, 92, "BorDlg", "Print");
ADialogTemplate->AddControl ( SS_CENTER | WS_VISIBLE | WS_CHILD | WS_GROUP, -1, 9, 9, 124, 8, DTCS_STATIC, "Printing");
ADialogTemplate->AddControl ( SS_CENTER | WS_VISIBLE | WS_CHILD | WS_GROUP, 101, 9, 17, 124, 8, DTCS_STATIC, "%s");
ADialogTemplate->AddControl ( SS_CENTER | WS_VISIBLE | WS_CHILD | WS_GROUP, 102, 9, 25, 124, 8, DTCS_STATIC, "on the %s Printer");
ADialogTemplate->AddControl ( SS_CENTER | WS_VISIBLE | WS_CHILD | WS_GROUP, 103, 9, 33, 124, 8, DTCS_STATIC, "connected to %s");
ADialogTemplate->AddControl ( SS_CENTER | WS_VISIBLE | WS_CHILD | WS_GROUP, 104, 9, 49, 124, 8, DTCS_STATIC, "Printing page %i on %i");
ADialogTemplate->AddControl ( WBS_DEFPUSHBUTTON | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE | WS_TABSTOP,
IDCANCEL, 55, 69, 33, 15, "WICSButton", NULL);
ADialogTemplate->AddControl ( 1 | WS_CHILD | WS_VISIBLE, -1, 6, 6, 130, 56, "BorShade", NULL);
PTPrinterAbortDlg Dlg = (PTPrinterAbortDlg) GetApplicationObject()->MakeWindow(
new TPrinterAbortDlg(ParentWin, ADialogTemplate, Printout->GetTitle(), Device, Port, fUserAbort) );
Dlg->SetMaxPage ( nMaxPage );
Dlg->SetCurrentPage (nFromPage);
GlobalUnlock (hDevNames);
if ( Dlg == NULL )
{
DeleteDC(PrnDC);
return result;
}
/* Disable the parent window, create the Yield Procedure and call it to enable screen
* Painting.
*/
EnableWindow(ParentWin->HWindow, FALSE);
YieldProcInst = (PTYieldProc) MakeProcInstance( (FARPROC) YieldProc, GetApplicationObject()->hInstance);
if ( !(*YieldProcInst)(fUserAbort) )
Error = SP_APPABORT;
// Get the page size
PageSize.x = GetDeviceCaps(PrnDC, HORZRES);
PageSize.y = GetDeviceCaps(PrnDC, VERTRES);
dpi.x = GetDeviceCaps(PrnDC, LOGPIXELSX);
dpi.y = GetDeviceCaps(PrnDC, LOGPIXELSY);
if ( !(*YieldProcInst)(fUserAbort) )
Error = SP_APPABORT;
for ( i = 0 ; i < nCopies && !Error ; i++ )
{
Flags = PFUNC_BOTH;
PageNumber = nFromPage;
if ( fBefore31 )
{
if ((Error = Escape(PrnDC, STARTDOC, strlen(Printout->GetTitle()), Printout->GetTitle(), NULL)) == 0 )
{
BOOL fMorePages = TRUE;
while ( fMorePages && !Error )
{
Dlg->SetCurrentPage (PageNumber);
(*YieldProcInst)(fUserAbort);
if ( fUserAbort )
Error = SP_APPABORT;
else
{
Printout->PrintPage(PrnDC, PageNumber, PageSize, dpi);
if ((Error = Escape(PrnDC, NEWFRAME, 0, NULL, NULL)) == 0 )
{
PageNumber++;
fMorePages = Printout->IsNextPage();
}
}
if ( PageNumber > nToPage )
fMorePages = FALSE;
}
if ( Error )
Escape(PrnDC, ABORTDOC, 0, NULL, NULL);
else
Escape(PrnDC, ENDDOC, 0, NULL, NULL);
}
}
else
{
DOCINFO DocInfo;
BOOL fMorePages = TRUE ;
DocInfo.cbSize = sizeof(DOCINFO);
DocInfo.lpszDocName = Printout->GetTitle();
DocInfo.lpszOutput = NULL;
Error = ( StartDoc (PrnDC, &DocInfo) > 0 ) ? 0 : SP_ERROR ;
while ( fMorePages && !Error )
{
Dlg->SetCurrentPage (PageNumber);
Error = ( StartPage (PrnDC) > 0 ) ? 0 : SP_ERROR ;
if ( !Error )
{
Printout->PrintPage(PrnDC, PageNumber, PageSize, dpi);
Error = EndPage (PrnDC);
if ( Error > 0 )
Error = 0 ;
if ( !Error )
{
/* Call the Abort Proc between pages
*/
(*YieldProcInst)(fUserAbort);
if ( fUserAbort )
Error = SP_APPABORT;
PageNumber++;
fMorePages = Printout->IsNextPage();
}
}
if ( PageNumber > nToPage )
fMorePages = FALSE;
}
if ( Error )
AbortDoc (PrnDC);
else
Error = EndDoc (PrnDC);
}
}
// Free allocated resources
FreeProcInstance((FARPROC) YieldProcInst);
EnableWindow(ParentWin->HWindow, TRUE);
delete Dlg;
DeleteDC(PrnDC);
if ( Error & SP_NOTREPORTED )
ReportError(ParentWin, Printout);
result = (Error > 0) && (!fUserAbort);
fUserAbort = FALSE;
return result;
}
void TPrinter::ReportError(PTWindowsObject ParentWin, PTPrintedPage Printout)
{
PTDialogTemplate ADialogTemplate;
Pchar Title;
Pchar ErrorCaption;
Pchar ErrorMsg;
Pchar ErrorTemplate = "'%s' was not printed. Reason: %s.";
Pchar ErrorText = new char [128];
switch (Error)
{
case SP_APPABORT:
ErrorMsg = "Printing canceled";
break;
case SP_ERROR:
ErrorMsg = "Error encountered during print";
break;
case SP_OUTOFDISK:
ErrorMsg = "Out of disk space";
break;
case SP_OUTOFMEMORY:
ErrorMsg = "Out of memory";
break;
case SP_USERABORT:
ErrorMsg = "Printing aborted in Print Manager";
break;
default:
ErrorMsg = "Unknown error";
break;
}
Title = Printout->GetTitle();
ErrorCaption = "Print Error";
wsprintf(ErrorText, ErrorTemplate, Title, ErrorMsg);
ADialogTemplate = new TDialogTemplate ( DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU,
18, 18, 217, 92, "BorDlg", Title);
ADialogTemplate->AddControl ( SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 100, 35, 15, 170, 8, DTCS_STATIC, ErrorCaption);
ADialogTemplate->AddControl ( SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 101, 12, 32, 193, 29, DTCS_STATIC, ErrorText);
ADialogTemplate->AddControl ( SS_ICON | WS_CHILD | WS_VISIBLE | WS_GROUP, 102, 12, 11, 16, 16, DTCS_STATIC, "");
ADialogTemplate->AddControl ( WBS_DEFPUSHBUTTON | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE | WS_TABSTOP,
IDOK, 92, 72, 33, 15, "WICSButton", NULL);
ADialogTemplate->AddControl ( 1 | WS_CHILD | WS_VISIBLE, -1, 7, 7, 203, 58, "BorShade", NULL);
GetApplicationObject()->ExecDialog( new TPrinterErrorDlg(ParentWin, ADialogTemplate) );
delete ErrorText;
}